use std::sync::Arc;
use tokio::sync::{mpsc, Mutex};
use tracing::{info, error, debug};
use anyhow::{Result, Context};
use uuid::Uuid;

use super::server::ScrcpyServer;
use super::socket::ScrcpySocket;
use crate::devices::control::handler::{ControlHandler, ControlEvent, DeviceReply};

pub struct ScrcpyClient {
    device_id: String,
    scid: String,
    port: u16,
    server: Arc<ScrcpyServer>,
    socket: Arc<Mutex<Option<ScrcpySocket>>>,
    control_handler: Arc<ControlHandler>,
}

impl ScrcpyClient {
    pub fn new(
        device_id: String,
        port: u16,
        event_sender: mpsc::Sender<ControlEvent>,
        reply_sender: mpsc::Sender<DeviceReply>,
    ) -> Self {
        let scid = Uuid::new_v4().to_string();
        let server = Arc::new(ScrcpyServer::new(device_id.clone(), scid.clone(), port));
        let control_handler = Arc::new(ControlHandler::new(
            device_id.clone(),
            event_sender,
            reply_sender,
        ));

        Self {
            device_id,
            scid,
            port,
            server,
            socket: Arc::new(Mutex::new(None)),
            control_handler,
        }
    }

    /// Initialize and start scrcpy connection
    pub async fn connect(&self, server_path: &std::path::PathBuf) -> Result<()> {
        info!("Connecting to device {}", self.device_id);

        // Push server to device
        self.server.push_server(server_path).await
            .context("Failed to push server")?;

        // Forward port
        self.server.forward_port().await
            .context("Failed to forward port")?;

        // Start server on device
        self.server.start().await
            .context("Failed to start server")?;

        // Wait for server to start
        tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;

        // Connect socket
        let address = format!("127.0.0.1:{}", self.port);
        info!("Connecting to scrcpy server at {}", address);

        let socket = ScrcpySocket::connect(
            address,
            self.control_handler.clone(),
        ).await
            .context("Failed to connect socket")?;

        let mut socket_guard = self.socket.lock().await;
        *socket_guard = Some(socket);

        info!("Successfully connected to device {}", self.device_id);
        Ok(())
    }

    /// Disconnect from device
    pub async fn disconnect(&self) -> Result<()> {
        info!("Disconnecting from device {}", self.device_id);

        // Close socket
        let mut socket_guard = self.socket.lock().await;
        if let Some(socket) = socket_guard.take() {
            socket.close().await;
        }

        // Stop server
        self.server.stop().await
            .context("Failed to stop server")?;

        info!("Disconnected from device {}", self.device_id);
        Ok(())
    }

    /// Get device screen size
    pub async fn get_screen_size(&self) -> Result<(u32, u32)> {
        self.server.get_screen_size().await
    }

    /// Get control handler for sending control messages
    pub fn control_handler(&self) -> Arc<ControlHandler> {
        self.control_handler.clone()
    }

    /// Check if connected
    pub async fn is_connected(&self) -> bool {
        let socket_guard = self.socket.lock().await;
        socket_guard.is_some()
    }

    pub fn device_id(&self) -> &str {
        &self.device_id
    }

    pub fn scid(&self) -> &str {
        &self.scid
    }

    pub fn port(&self) -> u16 {
        self.port
    }
}